package cn.xiuxius.embedded.runtime.rtx51;

import com.intellij.injected.editor.VirtualFileDelegate;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileSystem;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

public class TaskTransformedVirtualFile extends VirtualFile implements VirtualFileDelegate {

    private final VirtualFile original;

    public TaskTransformedVirtualFile(@NotNull VirtualFile original) {
        this.original = original;
    }

    @Override
    public @NotNull VirtualFile getDelegate() {
        return original;
    }



    private static String transformContent(String original) {
        // 把 (_task_ 数字) 替换为 /** _task_ 数字 **/
        return original.replaceAll("(_task_ \\d+)", "/** $1 **/");
    }

    private static String reverseTransformContent(String transformed) {
        // 把 /** _task_ 数字 **/ 替换回 _task_ 数字
        return transformed.replaceAll("/\\*\\* (_task_ \\d+) \\*\\*/", "$1");
    }

    @Override
    public byte @NotNull [] contentsToByteArray() throws IOException {
        String originalText = new String(original.contentsToByteArray(), StandardCharsets.UTF_8);
        String transformed = transformContent(originalText);
        return transformed.getBytes(StandardCharsets.UTF_8);
    }

    @Override
    public @NotNull InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(contentsToByteArray());
    }

    @Override
    public @NotNull OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
        return new ByteArrayOutputStream() {
            @Override
            public void close() throws IOException {
                super.close();
                String transformedText = new String(toByteArray(), StandardCharsets.UTF_8);
                String reverted = reverseTransformContent(transformedText);

                ApplicationManager.getApplication().runWriteAction(() -> {
                    try {
                        original.setBinaryContent(reverted.getBytes(StandardCharsets.UTF_8), newModificationStamp, newTimeStamp, requestor);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                });
            }
        };
    }

    // 下面的方法大多直接委托给原文件，保证行为一致

    @Override
    public @NotNull @NlsSafe String getName() {
        return original.getName();
    }

    @Override
    public @NotNull VirtualFileSystem getFileSystem() {
        return original.getFileSystem();
    }

    @Override
    public @NonNls @NotNull String getPath() {
        return original.getPath();
    }

    @Override
    public boolean isWritable() {
        return original.isWritable();
    }

    @Override
    public long getModificationStamp() {
        return original.getModificationStamp();
    }

    @Override
    public boolean isDirectory() {
        return original.isDirectory();
    }

    @Override
    public boolean isValid() {
        return original.isValid();
    }

    @Override
    public VirtualFile getParent() {
        return original.getParent();
    }

    @Override
    public VirtualFile @NotNull [] getChildren() {
        return original.getChildren();
    }

    @Override
    public long getTimeStamp() {
        return original.getTimeStamp();
    }

    @Override
    public long getLength() {
        try {
            return contentsToByteArray().length;
        } catch (IOException e) {
            return original.getLength();
        }
    }

    @Override
    public void refresh(boolean asynchronous, boolean recursive, @Nullable Runnable postRunnable) {
        original.refresh(asynchronous, recursive, postRunnable);
    }
}
